#include "msgsocket.h"
#include "databasemagr.h"
#include "command.h"
#include "config.h"

#include <QDebug>
#include <QDataStream>
#include <QApplication>
#include <QFileInfo>

MsgSocket::MsgSocket(QObject *parent, QTcpSocket *tcpSocket) :
    QObject(parent)
{
    m_nId = -1;

    if (tcpSocket == NULL) {
        m_tcpSocket = new QTcpSocket(this);
    }

    m_tcpSocket = tcpSocket;

    connect(m_tcpSocket, SIGNAL(readyRead()),
            this, SLOT(SltReadyRead()));
    connect(m_tcpSocket, SIGNAL(connected()),
            this, SLOT(SltConnected()));
    connect(m_tcpSocket, SIGNAL(disconnected()),
            this, SLOT(SltDisconnected()));
}

MsgSocket::~MsgSocket()
{

}

int MsgSocket::GetUserId() const
{
    return m_nId;
}

void MsgSocket::Close()
{
    m_tcpSocket->abort();
}

void MsgSocket::SltConnected()
{
    Q_EMIT signalConnected();
}

void MsgSocket::SltDisconnected()
{
    DataBaseMagr::Instance()->UpdateUserStatus(m_nId, OffLine);
    Q_EMIT signalDisConnected();
}

/**
 * @brief MsgSocket::SltReadyRead
 * 读取socket数据
 */
void MsgSocket::SltReadyRead()
{
    // 读取socket数据
    QByteArray reply = m_tcpSocket->readAll();
    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(reply, &jsonError);
    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            int nType = jsonObj.value("type").toInt();
            QJsonValue dataVal = jsonObj.value("data");

            switch (nType) {
            case Register: ParseReister(dataVal); break;
            case Login: ParseLogin(dataVal); break;
            case UserOnLine: ParseUserOnline(dataVal); break;
            case Logout:
                ParseLogout(dataVal);
                emit signalDisConnected();
                m_tcpSocket->abort();
                break;
            case UpdateHeadPic: ParseUpdateUserHead(dataVal); break;
            case AddFriend: ParseAddFriend(dataVal); break;
            case AddGroup: ParseAddGroup(dataVal); break;
            case CreateGroup: ParseCreateGroup(dataVal); break;
            case GetMyFriends: ParseGetMyFriend(dataVal); break;
            case GetMyGroups: ParseGetMyGroups(dataVal); break;

            case RefreshFriends: ParseRefreshFriend(dataVal); break;
            case RefreshGroups: ParseRefreshGroups(dataVal); break;

            case SendMsg:
            case SendFile:
            case SendPicture: ParseFriendMessages(reply); break;
            case SendGroupMsg: ParseGroupMessages(reply); break;
            case SendFace: ParseGroupMessages(reply); break;
            case SendFileOk: break;
            case GetFile: emit signalDownloadFile(dataVal); break;
            default:
                break;
            }
        }
    }
}

/**
 * @brief MsgSocket::ParseLogin
 * 解析登录信息
 * @param reply
 */
void MsgSocket::ParseLogin(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        QString strName = dataObj.value("name").toString();
        QString strPwd = dataObj.value("passwd").toString();
        QJsonObject jsonObj = DataBaseMagr::Instance()->CheckUserLogin(strName, strPwd);

        m_nId = jsonObj.value("id").toInt();
        qDebug() << "login" << jsonObj;

        if (m_nId > 0) Q_EMIT signalConnected();
        // 发送查询结果至客户端
        SltSendMessage(Login, jsonObj);;
    }
}

/**
 * @brief MsgSocket::ParseUserOnline
 * 用户上线
 * @param dataVal
 */
void MsgSocket::ParseUserOnline(const QJsonValue &dataVal)
{
    // data 的 value 是数组
    if (dataVal.isArray()) {
        QJsonArray jsonArray = dataVal.toArray();
        int nSize = jsonArray.size();
        for (int i = 0; i < nSize; ++i) {
            int nId = jsonArray.at(i).toInt();
            int nStatus = DataBaseMagr::Instance()->GetUserLineStatus(nId);
            // 给在线的好友通报一下状态
            if (OnLine == nStatus) {
                QJsonObject jsonObj;
                jsonObj.insert("id", m_nId);
                jsonObj.insert("text", "online");

                Q_EMIT signalMsgToClient(UserOnLine, nId, jsonObj);
            }
        }
    }

}

/**
 * @brief MsgSocket::ParseLogin
 * 解析登录信息
 * @param reply
 */
void MsgSocket::ParseLogout(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();

        QJsonArray array = dataObj.value("friends").toArray();
        int nId = dataObj.value("id").toInt();
        int nSize = array.size();

        DataBaseMagr::Instance()->UpdateUserStatus(nId, OffLine);

        for (int i = 0; i < nSize; ++i) {
            nId = array.at(i).toInt();
            int nStatus = DataBaseMagr::Instance()->GetUserLineStatus(nId);
            // 给在线的好友通报一下状态
            if (OnLine == nStatus) {
                QJsonObject jsonObj;
                jsonObj.insert("id", m_nId);
                jsonObj.insert("text", "offline");

                Q_EMIT signalMsgToClient(UserOffLine, nId, jsonObj);
            }
        }
    }
}

/**
 * @brief MsgSocket::ParseUpdateUserHead
 * 更新用户头像文件
 * @param dataVal
 */
void MsgSocket::ParseUpdateUserHead(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        int nId = dataObj.value("id").toInt();
        QString strHead = dataObj.value("head").toString();

        // 更新数据库
        DataBaseMagr::Instance()->UpdateUserHead(nId, strHead);

        // 通知其他在线好友，说我已经修改了头像
        QJsonArray jsonFriends =  dataObj.value("friends").toArray();
        QJsonObject jsonObj;
        // 是我在更新，我要去下载我的头像
        jsonObj.insert("id", nId);
        jsonObj.insert("head", strHead);

        for (int i = 0; i < jsonFriends.size(); i++) {
            nId = jsonFriends.at(i).toInt();
            Q_EMIT signalMsgToClient(UpdateHeadPic, nId, jsonObj);
        }
    }
}

/**
 * @brief MsgSocket::ParseReister
 * 解析注册信息
 * @param reply
 */
void MsgSocket::ParseReister(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        QString strName = dataObj.value("name").toString();
        QString strPwd = dataObj.value("passwd").toString();
        m_nId = DataBaseMagr::Instance()->RegisterUser(strName, strPwd);

        // 返回客户端
        QJsonObject json;
        json.insert("id", m_nId);
        json.insert("name", strName);
        json.insert("passwd", strPwd);

        // 发送查询结果至客户端
        SltSendMessage(Register, json);;
    }
}

/**
 * @brief MsgSocket::ParseAddFriend
 * 添加好友
 * @param reply
 */
void MsgSocket::ParseAddFriend(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject())
    {

        QJsonObject dataObj = dataVal.toObject();
        QString strName = dataObj.value("name").toString();
        QJsonObject jsonFriend = DataBaseMagr::Instance()->AddFriend(strName);
        int nId = jsonFriend.value("id").toInt();
        QString strMsg = jsonFriend.value("msg").toString();

        // 发送查询结果至客户端
        SltSendMessage(AddFriend, jsonFriend);

        if (nId < 0) return;

        // 给对方ID发送add请求
        QJsonObject jsonQuery = DataBaseMagr::Instance()->GetUserInfo(m_nId);
        QJsonObject jsonRequest;
        jsonRequest.insert("id", m_nId);
        jsonRequest.insert("name", jsonQuery.value("name").toString());
        jsonRequest.insert("head", jsonQuery.value("head").toString());
        jsonRequest.insert("msg", strMsg.isEmpty() ? "附加消息： 你好！" : strMsg);

        Q_EMIT signalMsgToClient(AddFriendRequist, nId, jsonRequest);
    }
}

/**
 * @brief MsgSocket::ParseAddGroup
 * 添加群组
 * @param dataVal
 */
void MsgSocket::ParseAddGroup(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject())
    {
        QJsonObject dataObj = dataVal.toObject();
        int nId = dataObj.value("id").toInt();
        QString strName = dataObj.value("name").toString();
        QJsonObject json = DataBaseMagr::Instance()->AddGroup(nId, strName);

        // 发送查询结果至客户端
        SltSendMessage(AddGroup, json);
    }
}

/**
 * @brief MsgSocket::ParseCreateGroup
 * 创建群组
 * @param dataVal
 */
void MsgSocket::ParseCreateGroup(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        int nId = dataObj.value("id").toInt();
        QString strName = dataObj.value("name").toString();
        QJsonObject json = DataBaseMagr::Instance()->CreateGroup(nId, strName);

        // 发送查询结果至客户端
        SltSendMessage(CreateGroup, json);
    }
}

/**
 * @brief MsgSocket::ParseGetMyFriend
 * 上线的时候获取我的好友
 * @param dataVal
 */
void MsgSocket::ParseGetMyFriend(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isArray())
    {
        QJsonArray array = dataVal.toArray();
        int nSize = array.size();
        // 先添加在线好友，在添加离线好友
        for (int i = 0; i < nSize; ++i)
        {
            int nId = array.at(i).toInt();
            jsonArray.append(DataBaseMagr::Instance()->GetUserStatus(nId));
        }
    }

    this->SltSendMessage(GetMyFriends, jsonArray);
}

/**
 * @brief MsgSocket::ParseGetMyGroups
 * 上线的时候获取我的群组
 * @param dataVal
 */
void MsgSocket::ParseGetMyGroups(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isObject()) {
        QJsonObject jsonObj = dataVal.toObject();
        // 群组ID
        int nId = jsonObj.value("id").toInt();
        jsonArray = DataBaseMagr::Instance()->GetGroupUsers(nId);
    }

    this->SltSendMessage(GetMyGroups, jsonArray);
}

/**
 * @brief MsgSocket::ParseRefreshFriend
 * @param dataVal
 */
void MsgSocket::ParseRefreshFriend(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isArray()) {
        QJsonArray array = dataVal.toArray();
        int nSize = array.size();
        for (int i = 0; i < nSize; ++i) {
            int nId = array.at(i).toInt();
            jsonArray.append(DataBaseMagr::Instance()->GetUserStatus(nId));
        }
    }

    this->SltSendMessage(RefreshFriends, jsonArray);
}

/**
 * @brief MsgSocket::ParseRefreshGroups
 * 刷新当前群组里面的好友信息
 * @param dataVal
 */
void MsgSocket::ParseRefreshGroups(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isObject()) {
        QJsonObject jsonObj = dataVal.toObject();
        // 群组ID
        int nId = jsonObj.value("id").toInt();
        jsonArray = DataBaseMagr::Instance()->GetGroupUsers(nId);
    }

    this->SltSendMessage(RefreshGroups, jsonArray);
}

/**
 * @brief MsgSocket::ParseMessages
 * 解析消息类，包括文字、图片、文件等
 * @param reply
 */
void MsgSocket::ParseFriendMessages(const QByteArray &reply)
{
    // 重新组装数据
    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(reply, &jsonError);
    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            int nType = jsonObj.value("type").toInt();
            QJsonValue dataVal = jsonObj.value("data");

            QJsonObject dataObj = dataVal.toObject();
            int nId = dataObj.value("to").toInt();
            Q_EMIT signalMsgToClient(nType, nId, dataObj);
        }
    }
}

/**
 * @brief MsgSocket::ParseGroupMessages
 * 处理群组消息转发
 * @param reply
 */
void MsgSocket::ParseGroupMessages(const QByteArray &reply)
{
    // 重新组装数据
    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(reply, &jsonError);
    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            int nType = jsonObj.value("type").toInt();
            QJsonValue dataVal = jsonObj.value("data");

            QJsonObject dataObj = dataVal.toObject();
            // 转发的群组id
            int nGroupId = dataObj.value("to").toInt();
            QString strMsg = dataObj.value("msg").toString();
            // 查询该群组下面的用户，一一转发消息
            QString name = DataBaseMagr::Instance()->GetUserName(m_nId);

            // 查询该群组里面的在线好友
            QJsonArray jsonArr = DataBaseMagr::Instance()->GetGroupUsers(nGroupId);
            if (jsonArr.size() < 2) return;
            for (int i = 1; i < jsonArr.size(); i++) {
                QJsonObject json = jsonArr.at(i).toObject();
                int nStatus = json.value("status").toInt();
                int nUserId = json.value("id").toInt();

                // 只给在线的好友转发消息
                if (OnLine == nStatus && m_nId != nUserId) {
                    // 重组消息
                    QJsonObject jsonMsg;
                    jsonMsg.insert("group", nGroupId);
                    jsonMsg.insert("id", m_nId);
                    jsonMsg.insert("name", name);
                    jsonMsg.insert("to", nUserId);
                    jsonMsg.insert("msg", strMsg);
                    jsonMsg.insert("head", DataBaseMagr::Instance()->GetUserHead(m_nId));

                    Q_EMIT signalMsgToClient(nType, nUserId, jsonMsg);
                }
            }
        }
    }
}

/**
 * @brief MsgSocket::SltSendMessage
 * @param type
 * @param json
 */
void MsgSocket::SltSendMessage(const quint8 &type, const QJsonValue &jsonVal)
{
    if (!m_tcpSocket->isOpen()) return;

    // 构建 Json 对象
    QJsonObject jsonObj;
    jsonObj.insert("type", type);
    jsonObj.insert("from", m_nId);
    jsonObj.insert("data", jsonVal);

    // 构建 Json 文档
    QJsonDocument document;
    document.setObject(jsonObj);
    m_tcpSocket->write(document.toJson(QJsonDocument::Compact));
}
